import json
import os
import random
import tkinter as tk
from pathlib import Path
from tkinter import messagebox


# 版本号 2.2.0
# 自定义函数
def create_frame_num():
    global frame_num
    global frame_file
    global num_mode
    global num_Result
    global num_Status
    global num_NumList
    global sp_max
    global sp_min
    global sp_times
    global fontsize
    try:
        frame_num.destroy()
    except:
        pass
    try:
        frame_file.destroy()
    except:
        pass
    frame_num = tk.Frame(root)
    frame_num.pack(side='left', fill='both', expand=True)
    num_label_title = tk.Label(frame_num,
                               text='随机数抽取',
                               width=15,
                               height=1,
                               font=('楷体', fontsize + 16))
    num_label_title.pack(fill='x')
    frame_num_1 = tk.Frame(frame_num)
    frame_num_1.pack(fill='both', expand=True)
    frame_num_2 = tk.Frame(frame_num)
    frame_num_2.pack(fill='both', expand=True)
    # Control Area
    ## Row 1
    label_min = tk.Label(frame_num_1,
                         text='最小号数',
                         width=10,
                         font=('楷体', fontsize))
    label_min.grid(row=0, column=0, padx=4, pady=2, sticky="nsew")
    sp_min = tk.Spinbox(frame_num_1,
                        from_=1,
                        to=100,
                        width=10,
                        font=('楷体', fontsize - 2))
    sp_min.grid(row=0, column=1, padx=4, pady=2, sticky="nsew")
    label_max = tk.Label(frame_num_1,
                         text='最大号数',
                         width=10,
                         font=('楷体', fontsize))
    label_max.grid(row=0, column=2, padx=4, pady=2, sticky="nsew")
    sp_max = tk.Spinbox(frame_num_1,
                        from_=1,
                        to=100,
                        width=10,
                        font=('楷体', fontsize - 2))
    sp_max.grid(row=0, column=3, padx=4, pady=2, sticky="nsew")
    ## Row 2
    label_times = tk.Label(frame_num_1,
                           text='抽取个数',
                           width=10,
                           font=('楷体', fontsize))
    label_times.grid(row=1, column=0, padx=4, pady=2, sticky="nsew")
    sp_times = tk.Spinbox(frame_num_1,
                          from_=1,
                          to=10,
                          width=10,
                          font=('楷体', fontsize - 2))
    sp_times.grid(row=1, column=1, padx=4, pady=2, sticky="nsew")
    cb_catchmode1 = tk.Checkbutton(frame_num_1,
                                   text='是否允许仅被抽一次',
                                   width=20,
                                   variable=num_mode,
                                   font=('楷体', fontsize - 2))
    cb_catchmode1.grid(row=1, column=2, columnspan=2, padx=4, pady=2)
    ## Row 3
    button_Clean = tk.Button(frame_num_1,
                             text='重置列表',
                             width=10,
                             font=('楷体', fontsize))
    button_Clean.grid(row=2, column=0, padx=4, pady=2, sticky="nsew")
    button_IntoList = tk.Button(frame_num_1,
                                text='形成列表',
                                width=10,
                                font=('楷体', fontsize))
    button_IntoList.grid(row=2, column=1, padx=4, pady=2, sticky="nsew")
    button_Begim = tk.Button(frame_num_1,
                             text='开始抽取',
                             width=20,
                             font=('楷体', fontsize))
    button_Begim.grid(row=2,
                      column=2,
                      columnspan=2,
                      padx=4,
                      pady=2,
                      sticky="nsew")
    # Reflact Area
    label_result = tk.Label(frame_num_2,
                            textvariable=num_Result,
                            height=1,
                            width=40,
                            anchor='sw',
                            justify='left',
                            font=('楷体', fontsize + 3))
    label_result.pack(fill='both', expand=True)
    file_label_status = tk.Label(frame_num_2,
                                 textvariable=num_Status,
                                 width=40,
                                 height=10,
                                 justify='left',
                                 anchor='sw',
                                 wraplength=400,
                                 bg='black',
                                 fg='white',
                                 font=('宋体', fontsize))
    file_label_status.pack(fill='both', expand=True)

    # Functions
    def IntoList():
        global sp_min
        global sp_max
        global num_NumList
        if int(sp_min.get()) < int(sp_max.get()):
            num_NumList = list(range(int(sp_min.get()), int(sp_max.get()) + 1))
            num_Status.set(
                str(num_Status.get()) + '\n' + '刷新了新的号数序列，长度为' +
                str(len(num_NumList)))
        else:
            num_Result.set('Range Error')
            num_Status.set(
                str(num_Status.get()) + '\n' + '您的最小号数不小于最大号数，请重新设置')
        print(num_NumList)

    def begin():
        global num_mode
        global num_Result
        global sp_times
        global num_NumList
        global sp_min
        global sp_max
        num_Result.set('')
        if int(sp_times.get()) > 10:
            num_Result.set('Times Error')
            num_Status.set(str(num_Status.get()) + '\n' + '请保证次数不大于10次')
        else:
            if len(num_NumList) >= 1:
                for i in range(int(sp_times.get())):
                    if len(num_NumList) >= 1:
                        Num = random.randint(0, len(num_NumList) - 1)
                        num_Result.set(num_Result.get() + ' ' +
                                       str(num_NumList[Num]))
                        if num_mode.get() == 1:
                            num_NumList.pop(Num)
                    else:
                        num_Status.set(
                            str(num_Status.get()) + '\n' +
                            'RangeError 列表长度过短，可通过再次点击“形成列表”解决')
                        break
                num_Status.set(
                    str(num_Status.get()) + '\n' + '抽取了' +
                    str(num_Result.get()))
                if num_mode.get() == 1:
                    num_Status.set(
                        str(num_Status.get()) + '\n' + '剩余' +
                        str(len(num_NumList)) + '人未被抽取')
            else:
                if messagebox.askquestion("An Error",
                                          "当前号数名单过短，是否开始新的抽取周期") == "yes":
                    IntoList()
                else:
                    num_Status.set(
                        str(num_Status.get()) + '\n' +
                        '列表长度过短，可通过再次点击“形成列表”解决')
            print(num_NumList)

    def reset():
        global num_NumList
        num_NumList = []
        num_Status.set(num_Status.get() + "\n已重置")
        num_Result.set("")

    # Button Event
    button_IntoList.config(command=IntoList)
    button_Begim.config(command=begin)
    button_Clean.config(command=reset)
    btn_mode_file.config(state='normal')
    btn_mode_num.config(state='disabled')


def create_frame_file():
    global frame_num
    global frame_file
    global file_mode
    global file_Result
    global file_Status
    global file_NameList
    global file_path
    global fontsize
    file_path = tk.StringVar()
    file_path.set('请输入文件路径')
    try:
        frame_num.destroy()
    except:
        pass
    try:
        frame_file.destroy()
    except:
        pass
    btn_mode_file.config(state='disabled')
    btn_mode_num.config(state='normal')
    frame_file = tk.Frame(root, width=750)
    frame_file.pack(side='left', fill='both', expand=True)
    file_label_title = tk.Label(frame_file,
                                text='随机人名抽取',
                                width=15,
                                height=1,
                                font=('楷体', fontsize + 16))
    file_label_title.pack(fill='x', expand=True)
    file_frame1 = tk.Frame(frame_file)
    file_frame1.pack(fill='both', expand=True)
    file_frame2 = tk.Frame(frame_file)
    file_frame2.pack(fill='both', expand=True)
    file_btn_readfile = tk.Button(file_frame1,
                                  text='读取文件至内存',
                                  width=40,
                                  font=('楷体', fontsize))
    file_btn_readfile.grid(row=1,
                           column=0,
                           columnspan=4,
                           padx=4,
                           pady=2,
                           sticky='nsew')
    file_label_times = tk.Label(file_frame1,
                                text='抽取人数',
                                width=10,
                                font=('楷体', fontsize))
    file_label_times.grid(row=2, column=0, padx=4, pady=2, sticky='nesw')
    file_sp_times = tk.Spinbox(file_frame1,
                               from_=1,
                               to=3,
                               width=10,
                               font=('楷体', fontsize - 2))
    file_sp_times.grid(row=2, column=1, padx=4, pady=2, sticky='nesw')
    file_cb_mode = tk.Checkbutton(file_frame1,
                                  text='是否允许仅被抽一次',
                                  width=20,
                                  variable=file_mode,
                                  font=('楷体', fontsize - 2))
    file_cb_mode.grid(row=2,
                      column=3,
                      columnspan=2,
                      padx=4,
                      pady=2,
                      sticky='nesw')
    file_btn_clean = tk.Button(file_frame1,
                               text='清空状态区',
                               width=20,
                               font=('楷体', fontsize))
    file_btn_clean.grid(row=3,
                        column=0,
                        columnspan=2,
                        padx=4,
                        pady=2,
                        sticky='nesw')
    file_btn_begin = tk.Button(file_frame1,
                               text='开始抽取',
                               width=10,
                               font=('楷体', fontsize))
    file_btn_begin.grid(row=3,
                        column=2,
                        columnspan=2,
                        padx=4,
                        pady=2,
                        sticky='nesw')
    file_label_result = tk.Label(file_frame2,
                                 textvariable=file_Result,
                                 height=1,
                                 width=40,
                                 anchor='sw',
                                 justify='left',
                                 font=('楷体', fontsize + 3))
    file_label_result.pack(fill='both', expand=True)
    file_label_status = tk.Label(file_frame2,
                                 textvariable=file_Status,
                                 width=40,
                                 height=10,
                                 justify='left',
                                 anchor='sw',
                                 wraplength=400,
                                 bg='black',
                                 fg='white',
                                 font=('楷体', fontsize))
    file_label_status.pack(fill='both', expand=True)

    def NameIntoList():
        global file_NameList
        file_NameList = []
        try:
            with open('names.txt', 'r') as n:
                content = n.read()
                file_NameList = content.split('\n')
            file_Status.set(file_Status.get() + '\n读取成功')
            print(file_NameList)
        except:
            messagebox.showwarning('An Error', '请确保有names.txt文件与程序在同一目录')

    def begin():
        global file_NameList
        global file_mode
        global file_Result
        file_Result.set('')
        if int(file_sp_times.get()) > 3:
            file_Result.set('Times Error')
            file_Status.set(str(file_Status.get()) + '\n' + '请保证次数不大于3次')
        else:
            if len(file_NameList) >= 1:
                for i in range(int(file_sp_times.get())):
                    if len(file_NameList) >= 1:
                        Num = random.randint(0, len(file_NameList) - 1)
                        file_Result.set(file_Result.get() + ' ' +
                                        str(file_NameList[Num]))
                        if file_mode.get() == 1:
                            file_NameList.pop(Num)
                    else:
                        file_Status.set(
                            str(file_Status.get()) + '\n' +
                            'RangeError 列表长度过短，可通过再次点击“形成列表”解决')
                        break
                file_Status.set(
                    str(file_Status.get()) + '\n' + '抽取了' +
                    str(file_Result.get()))
                if file_mode.get() == 1:
                    file_Status.set(
                        str(file_Status.get()) + '\n' + '剩余' +
                        str(len(file_NameList)) + '人未被抽取')
            else:
                if messagebox.askquestion("An Error",
                                          "当前人员名单过短，是否开始新的抽取周期") == "yes":
                    NameIntoList()
                else:
                    file_Status.set(
                        str(file_Status.get()) + '\n' +
                        '列表长度过短，可通过再次点击“形成列表”解决')
            print(file_NameList)

    def clean():
        global file_Result
        global file_Status
        file_Result.set('设置好信息后请先按下读取文件按钮再抽取')
        file_Status.set('已清空')

    file_btn_clean.config(command=clean)
    file_btn_readfile.config(command=NameIntoList)
    file_btn_begin.config(command=begin)


# 主程序
root = tk.Tk()
root.title('抽取工具')
root.geometry('650x400')
# root.resizable(0, 0)
root.attributes('-topmost', 'true')
num_mode = tk.IntVar()
num_Result = tk.StringVar()
num_Result.set('设置好信息后请先按下形成列表按钮再抽取')
num_Status = tk.StringVar()
num_NumList = []
file_mode = tk.IntVar()
file_Result = tk.StringVar()
file_Result.set('设置好信息后请先按下读取文件按钮再抽取')
file_Status = tk.StringVar()
file_NameList = []
fontsize = 12

## 读取自定义设置
settings = {
    'width': 650,
    'height': 400,
    'autosize': True,
    'topmost': True,
    'fontsize': 12,
}

path = Path('settings.json')
if path.exists():
    contents = path.read_text()
    settings = json.loads(contents)
else:
    contents = json.dumps(settings,
                          sort_keys=True,
                          indent=4,
                          separators=(',', ':'))
    path.write_text(contents)
## 尝试读取内容
try:
    if settings['autosize'] == True:
        pass
    else:
        root.geometry(str(settings['width']) + 'x' + str(settings['height']))
    if settings['topmost'] == True:
        root.attributes('-topmost', 'true')
    else:
        root.attributes('-topmost', 'false')
    fontsize = settings['fontsize']
except (KeyError) as e:
    messagebox.showwarning(
        '个性化定义出错',
        '你的自定义文件settings.json中没有定义完全\n需要包含：width, height, autosize, topmost\n删除掉源文件并重启应用程序即可解决问题\n现将以默认格式启动程序'
    )
    settings = {
        'width': 650,
        'height': 400,
        'autosize': True,
        'topmost': True,
        'fontsize': 12,
    }
    if settings['autosize'] == True:
        pass
    else:
        root.geometry(str(settings['width']) + 'x' + str(settings['height']))
    if settings['topmost'] == True:
        root.attributes('-topmost', 'true')
    else:
        root.attributes('-topmost', 'false')
    fontsize = settings['fontsize']

# my_font=font.Font(size=fontsize)
# 第一部分 制作菜单栏
menubar = tk.Menu(root)

menubar.add_command(
    label='源文件目录',
    command=lambda: os.system('start explorer.exe "{}" '.format(
        os.path.dirname(os.path.abspath(__file__)))))

aboutmenu = tk.Menu(menubar, tearoff=False)
aboutmenu.add_command(
    label='软件信息',
    command=lambda: os.system('start https://gitee.com/TuChenjia/my-python'))
aboutmenu.add_command(label='源代码网页',
                      command=lambda: messagebox.showinfo(
                          title='关于', message='软件名称：随机数抽取\n作者：TCJ\n版本号：2.1.6'))
menubar.add_cascade(label='关于', menu=aboutmenu)

root.config(menu=menubar)
# 第二部分 布局根界面，用于切换抽取模式
frame_mode = tk.Frame(root, width=200)
frame_mode.pack(side='left', fill='y')
btn_mode_num = tk.Button(frame_mode,
                         text='抽取随机数',
                         command=create_frame_num,
                         state='normal',
                         font=('楷体', fontsize))
btn_mode_num.pack(side='top', fill='both', expand=True)
btn_mode_file = tk.Button(frame_mode,
                          text='从文件中抽取',
                          command=create_frame_file,
                          state='active',
                          font=('楷体', fontsize))
btn_mode_file.pack(side='top', fill='both', expand=True)

create_frame_num()
root.mainloop()
